package manager

import (
	"battle-server/config"
	"battle-server/model"
	"errors"
	"fmt"
	gameModel "game-server/model"
	"log"
	"sync"
)

// HeroCache 存储所有英雄数据的全局缓存
var (
	HeroCache        map[int]*gameModel.Hero          // 英雄ID -> 英雄信息
	SkillCache       map[int]*gameModel.Skill         // 技能ID -> 技能信息
	HeroSkillCache   map[int][]*gameModel.Skill       // 英雄ID -> 该英雄所有技能
	SkillEffectCache map[int][]*gameModel.SkillEffect // 技能ID -> 该技能所有效果
	heroCacheMutex   sync.RWMutex
)

// InitHeroData 从数据库加载英雄、技能和效果数据到内存
func InitHeroData() {
	log.Println("开始加载英雄数据...")

	// 初始化缓存映射
	HeroCache = make(map[int]*gameModel.Hero)
	SkillCache = make(map[int]*gameModel.Skill)
	HeroSkillCache = make(map[int][]*gameModel.Skill)
	SkillEffectCache = make(map[int][]*gameModel.SkillEffect)

	// 加载所有英雄数据
	var heroes []*gameModel.Hero
	if err := config.DB.Find(&heroes).Error; err != nil {
		log.Printf("加载英雄数据失败: %v", err)
		return
	}

	// 将英雄数据存入缓存
	for _, hero := range heroes {
		HeroCache[hero.HeroID] = hero
	}

	log.Printf("已加载 %d 个英雄", len(heroes))

	// 加载所有技能数据
	var skills []*gameModel.Skill
	if err := config.DB.Find(&skills).Error; err != nil {
		log.Printf("加载技能数据失败: %v", err)
		return
	}

	// 将技能数据存入缓存
	for _, skill := range skills {
		SkillCache[skill.SkillID] = skill

		// 构建英雄ID到技能列表的映射
		HeroSkillCache[skill.HeroID] = append(HeroSkillCache[skill.HeroID], skill)
	}

	log.Printf("已加载 %d 个技能", len(skills))

	// 加载所有技能效果数据
	var effects []*gameModel.SkillEffect
	if err := config.DB.Find(&effects).Error; err != nil {
		log.Printf("加载技能效果数据失败: %v", err)
		return
	}

	// 将技能效果数据存入缓存
	for _, effect := range effects {
		SkillEffectCache[effect.SkillID] = append(SkillEffectCache[effect.SkillID], effect)
	}

	log.Printf("已加载 %d 个技能效果", len(effects))

	log.Println("英雄数据加载完成")
}

// GetHeroByID 根据ID获取英雄数据
func GetHeroByID(heroID int) *gameModel.Hero {
	heroCacheMutex.RLock()
	defer heroCacheMutex.RUnlock()

	if hero, ok := HeroCache[heroID]; ok {
		return hero
	}
	return nil
}

// GetHeroSkills 获取英雄技能
func GetHeroSkills(heroID int) []*gameModel.Skill {
	result, exists := HeroSkillCache[heroID]
	if !exists {
		return nil
	}
	return result
}

// GetSkillEffects 获取技能效果
func GetSkillEffects(skillID int) ([]*gameModel.SkillEffect, error) {
	effects, exists := SkillEffectCache[skillID]
	if !exists {
		return nil, fmt.Errorf("skill %d not found", skillID)
	}
	return effects, nil
}

// 获取直接生效的技能效果
func GetDirectEffect(skillId int) (*gameModel.SkillEffect, error) {
	skillEffects, err := GetSkillEffects(skillId)
	if err != nil {
		return nil, fmt.Errorf("skill effect %d is nil", skillId)
	}
	for _, skillEffect := range skillEffects {
		if skillEffect.Duration == 0 {
			return skillEffect, nil
		}

	}
	return nil, fmt.Errorf("skill effect %d is nil", skillId)
}

// 判断技能是不是大招
func IsSkillIsUltimate(skillId int) bool {
	skill, exists := SkillCache[skillId]
	if !exists {
		return false
	}
	return skill.Ultimate == 1
}

// 获取技能
func GteSkillById(skillId int) (*gameModel.Skill, error) {
	skill, exists := SkillCache[skillId]
	if !exists {
		return nil, fmt.Errorf("skill %d not found", skillId)
	}
	return skill, nil
}

// CreateBattleHero 创建战斗英雄
func CreateBattleHero(heroID int, playerID int, position int) (*model.FightHero, error) {
	// 获取英雄基础信息
	hero := GetHeroByID(heroID)
	if hero == nil {
		return nil, errors.New("英雄不存在")
	}

	// 创建战斗英雄
	battleHero := &model.FightHero{
		HeroId:          heroID,
		HeroName:        hero.HeroName,
		Job:             hero.ClassID,
		JobName:         getJobName(hero.ClassID),
		MaxHp:           hero.Hp,
		CurrentHp:       hero.Hp,
		Attack:          hero.Atk,
		Defense:         hero.Def,
		Speed:           hero.Spd,
		CritRate:        hero.CritRate,
		CritDamage:      hero.CritDamage,
		MagicPower:      hero.MagicPower,
		HealEffect:      hero.HealEffect,
		DamageReduction: hero.DamageReduction,
		PlayerId:        playerID,
		Position:        position,
		Shield:          0,
		IsAlive:         true,
		ActionTaken:     false,
		Buffs:           make([]model.Effect, 0),
		Debuffs:         make([]model.Effect, 0),
		SkillCDs:        make(map[int]int),
		Skills:          make([]int, 0),
	}

	// 获取英雄技能
	skills := GetHeroSkills(heroID)
	if skills == nil {
		return nil, errors.New("英雄技能不存在")
	}

	// 初始化技能ID列表和CD
	for _, skill := range skills {
		skillID := int(skill.SkillID)
		battleHero.Skills = append(battleHero.Skills, skillID)
		battleHero.SkillCDs[skillID] = 0
	}

	return battleHero, nil
}

// 获取职业名称
func getJobName(classID int) string {
	switch classID {
	case 1:
		return "战士"
	case 2:
		return "法师"
	case 3:
		return "刺客"
	case 4:
		return "坦克"
	case 5:
		return "射手"
	case 6:
		return "辅助"
	case 7:
		return "元素使"
	case 8:
		return "召唤师"
	default:
		return "未知职业"
	}
}
